'use client';

import {
  type ChangeEvent,
  type FormEvent,
  useEffect,
  useRef,
  useState,
} from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import diff from 'microdiff';
import type { IDifference, IPostBadge, IQueryPostDetails } from '@/interfaces';
import type {
  TBadgeBackgroundColorMode,
  TBadgeColorMode,
  TBody,
} from '@/types';
import useToast from '@/hooks/useToast';
import { getDiffData, getFilterData, isEmpty, mergeObject } from '@/lib/tool';
import { BADGE_BACKGROUND_COLOR_MODE, BADGE_COLOR_MODE } from '@/lib/constant';
import IroItem from '@/app/[locale]/admin/forum/post/other/IroItem';
import {
  createPostBadge,
  removePostBadge,
  updatePostBadge,
} from '@/services/api';
import classNames from 'classnames';

const defaultForm: any = {
  name: '',
  sort: 0,
  reason: '',
  colorMode: 'DEFAULT',
  color: '#ffffff',
  backgroundColorMode: 'DEFAULT',
  backgroundColor: '#0dcaf0',
  roundedPill: false,
};

export default function UpdatePostBadge(
  this: any,
  {
    details,
  }: {
    details: IQueryPostDetails;
  },
) {
  const { show } = useToast();
  const [form, setForm] = useState<{
    name?: string;
    sort?: number;
    reason?: string;
    colorMode?: TBadgeColorMode;
    color?: string;
    backgroundColorMode?: TBadgeBackgroundColorMode;
    backgroundColor?: string;
    roundedPill?: boolean;
  }>(defaultForm);
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const [currentItemId, setCurrentItemId] = useState<number>();
  const [currentRemoveItemId, setCurrentRemoveItemId] = useState<number>();
  const queryClient = useQueryClient();
  const selectColorModeRef = useRef<HTMLSelectElement>(null);
  const selectBackgroundColorModeRef = useRef<HTMLSelectElement>(null);
  const [selectColorMode, setSelectColorMode] = useState('HEX');
  const [selectBackgroundColorMode, setSelectBackgroundColorMode] =
    useState('HEX');

  const createPostBadgeMutation = useMutation(
    async (
      variables: TBody<{
        postId: number;
        name: string;
      }>,
    ) => {
      await createPostBadge(variables);
      await queryClient.invalidateQueries([
        '/forum',
        '/posts',
        details.basic.id,
        '/details',
      ]);
    },
  );
  const updatePostBadgeMutation = useMutation(
    async (
      variables: TBody<{
        name?: string;
        sort?: number;
        reason?: string;
        colorMode?: TBadgeColorMode;
        color?: string;
        backgroundColorMode?: TBadgeBackgroundColorMode;
        backgroundColor?: string;
        roundedPill?: boolean;
      }>,
    ) => {
      await updatePostBadge(variables);
      await queryClient.invalidateQueries([
        '/forum',
        '/posts',
        details.basic.id,
        '/details',
      ]);
    },
  );
  const removePostBadgeMutation = useMutation(
    async (variables: TBody<void>) => {
      await removePostBadge(variables);
      await queryClient.invalidateQueries([
        '/forum',
        '/posts',
        details.basic.id,
        '/details',
      ]);
    },
  );

  useEffect(() => {
    const differences = diff(defaultForm, form);
    setDifferenceData(differences);
  }, [form]);

  function onChangeForm(e: ChangeEvent<HTMLSelectElement | HTMLInputElement>) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'roundedPill') {
      setForm({ ...form, roundedPill: value === 'true' });
    } else if (name === 'sort') {
      setForm({ ...form, sort: parseInt(value) });
    } else if (name === 'selectColorMode') {
      setSelectColorMode(value);
    } else if (name === 'selectBackgroundColorMode') {
      setSelectBackgroundColorMode(value);
    } else {
      setForm({ ...form, [name]: value });
    }
  }

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      checkForm();
      const body = getFilterData(getDiffData(differenceData));
      if (isEmpty(body)) {
        show({
          type: 'SUCCESS',
          message: '保存完成',
        });
        return;
      }

      if (currentItemId) {
        if (
          body.name &&
          details.basic.badges.find((item) => item.name === body.name)
        ) {
          delete body.name;
        }

        await updatePostBadgeMutation.mutateAsync({
          id: currentItemId,
          data: body,
        });
      } else {
        await createPostBadgeMutation.mutateAsync({
          data: {
            name: body.name,
            postId: details.basic.id,
          },
        });

        setForm(defaultForm);
      }

      clearData();
      show({
        type: 'SUCCESS',
        message: '保存完成',
      });
    } catch (e) {
      if (currentItemId) {
        updatePostBadgeMutation.reset();
      } else {
        createPostBadgeMutation.reset();
      }

      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickItem(item: IPostBadge) {
    setCurrentItemId(item.id);
    setForm(mergeObject(item, form));
  }

  function onClickCancel() {
    setCurrentItemId(undefined);
    setForm({ ...form, ...defaultForm });
  }

  async function onClickRemove(item: IPostBadge) {
    try {
      setCurrentRemoveItemId(item.id);

      await removePostBadgeMutation.mutateAsync({
        id: item.id,
      });

      setCurrentItemId(undefined);
      clearData();
      show({
        type: 'SUCCESS',
        message: '删除完成',
      });
    } catch (e) {
      removePostBadgeMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function clearData() {
    setDifferenceData([]);
    setCurrentRemoveItemId(undefined);
  }

  function checkForm() {
    const name = form.name;

    if (!name) {
      throw '徽章名称不能为空';
    }

    if (
      !currentItemId &&
      details.basic.badges.find((item) => item.name === name)
    ) {
      throw '该徽章名称已存在';
    }
  }

  function changeColorCallback(color: string) {
    if (!color) {
      return;
    }

    setForm({ ...form, color });
  }

  function changeBackgroundColorCallback(color: string) {
    if (!color) {
      return;
    }

    setForm({ ...form, backgroundColor: color });
  }

  return (
    <div className="row">
      <div className="col">
        <div className="vstack gap-4">
          <div>
            <div className="table-responsive">
              <table className="table table-hover align-middle">
                <thead>
                  <tr className="text-nowrap">
                    <th scope="col" className="w-10 fw-normal">
                      名称
                    </th>
                    <th scope="col" className="w-10 fw-normal">
                      排序
                    </th>
                    <th scope="col" className="w-10 fw-normal">
                      理由
                    </th>
                    <th scope="col" className="w-10 fw-normal">
                      颜色
                    </th>
                    <th scope="col" className="w-10 fw-normal">
                      背景颜色
                    </th>
                    <th scope="col" className="w-10 fw-normal">
                      椭圆形样式
                    </th>
                    <th scope="col" className="w-10"></th>
                  </tr>
                </thead>
                <tbody>
                  {details.basic.badges.map((item) => {
                    return (
                      <tr
                        key={item.id}
                        className={classNames(
                          'text-nowrap',
                          currentItemId === item.id ? 'table-active' : false,
                        )}
                      >
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >
                          <span
                            className={classNames(
                              'badge',
                              item.roundedPill ? 'rounded-pill' : false,
                            )}
                            style={{
                              color:
                                item.colorMode === 'DEFAULT'
                                  ? '#ffffff'
                                  : item.color,
                              backgroundColor:
                                item.backgroundColorMode === 'DEFAULT'
                                  ? '#0dcaf0'
                                  : item.backgroundColor,
                            }}
                          >
                            {item.name}
                          </span>
                        </td>
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >
                          {item.sort}
                        </td>
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >
                          {item.reason}
                        </td>
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >{`${BADGE_COLOR_MODE[item.colorMode]} (${
                          item.color
                        })`}</td>
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >{`${
                          BADGE_BACKGROUND_COLOR_MODE[item.backgroundColorMode]
                        } (${item.backgroundColor})`}</td>
                        <td
                          className="cursor-pointer"
                          onClick={onClickItem.bind(this, item)}
                        >
                          {item.roundedPill ? '是' : '否'}
                        </td>
                        <td>
                          {currentItemId === item.id && (
                            <button
                              onClick={onClickCancel}
                              className="btn btn-sm btn-light me-2"
                              type="button"
                            >
                              取消
                            </button>
                          )}

                          <button
                            disabled={
                              currentRemoveItemId === item.id &&
                              removePostBadgeMutation.isLoading
                            }
                            onClick={onClickRemove.bind(this, item)}
                            className="btn btn-sm btn-danger"
                            type="button"
                          >
                            {currentRemoveItemId === item.id &&
                            removePostBadgeMutation.isLoading ? (
                              <span
                                className="spinner-border spinner-border-sm me-2"
                                role="status"
                                aria-hidden="true"
                              ></span>
                            ) : (
                              <i className="bi bi-trash me-2"></i>
                            )}
                            删除
                          </button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>

            {details.basic.badges.length === 0 && (
              <div className="text-muted">暂无徽章</div>
            )}
          </div>

          {form.name && (
            <div className="card position-relative">
              <div className="card-body text-center">
                <div
                  className="position-absolute text-muted"
                  style={{
                    left: '-1rem',
                    top: '-0.7rem',
                    transform: 'skew(15deg)',
                  }}
                >
                  预览
                </div>
                <span
                  className={classNames(
                    'badge me-2',
                    form.roundedPill ? 'rounded-pill' : false,
                  )}
                  style={{
                    color:
                      form.colorMode === 'DEFAULT' ? '#ffffff' : form.color,
                    backgroundColor:
                      form.backgroundColorMode === 'DEFAULT'
                        ? '#0dcaf0'
                        : form.backgroundColor,
                  }}
                >
                  {form.name}
                </span>
                <span>{details.basic.name}</span>
              </div>
            </div>
          )}

          <form onSubmit={onClickSave} className="vstack gap-4">
            <div>
              <label className="form-label">名称</label>
              <input
                type="text"
                className="form-control"
                name="name"
                value={form.name}
                onChange={onChangeForm}
                aria-describedby="name"
                placeholder="请输入徽章名称"
              />
            </div>

            {currentItemId && (
              <>
                <div>
                  <label className="form-label">排序</label>
                  <input
                    min={0}
                    type="number"
                    className="form-control"
                    name="sort"
                    value={form.sort}
                    onChange={onChangeForm}
                    aria-describedby="sort"
                    placeholder="请输入排序，最小值为 0；排序规则为从小到大排序"
                  />
                </div>

                <div>
                  <label className="form-label">理由</label>
                  <input
                    type="text"
                    className="form-control"
                    name="reason"
                    value={form.reason}
                    onChange={onChangeForm}
                    aria-describedby="reason"
                    placeholder="请输入理由"
                  />
                </div>

                <div>
                  <label className="form-label">颜色模式</label>
                  <div className="form-control user-select-none">
                    {Object.keys(BADGE_COLOR_MODE).map((item) => {
                      return (
                        <div
                          key={item}
                          className="form-check form-check-inline"
                        >
                          <input
                            id={`yw-badge-colorMode-${item}`}
                            name="colorMode"
                            className="form-check-input"
                            type="radio"
                            onChange={onChangeForm}
                            value={item}
                            checked={form.colorMode === item}
                          />
                          <label
                            className="form-check-label"
                            htmlFor={`yw-badge-colorMode-${item}`}
                          >
                            {BADGE_COLOR_MODE[item]}
                          </label>
                        </div>
                      );
                    })}
                  </div>
                </div>

                {form.colorMode === 'CUSTOM' && (
                  <div>
                    <label className="form-label">颜色</label>
                    <div className="row align-items-center gap-4">
                      <div className="col-4">
                        <div className="vstack gap-4">
                          <div className="row gap-4 align-items-center">
                            <div className="col-2"></div>
                            <div className="col">
                              <select
                                ref={selectColorModeRef}
                                name="selectColorMode"
                                value={selectColorMode}
                                onChange={onChangeForm}
                                className="form-select"
                                aria-label="selectColorMode"
                                placeholder="请选择颜色输出类型"
                              >
                                <option value="HEX">HEX</option>
                                <option value="RGB">RGB</option>
                                <option value="RGBA">RGBA</option>
                                <option value="HSL">HSL</option>
                                <option value="HSLA">HSLA</option>
                              </select>
                            </div>
                          </div>

                          <input
                            type="text"
                            className="form-control"
                            name="color"
                            value={form.color}
                            onChange={onChangeForm}
                            aria-describedby="color"
                            placeholder="请输入颜色"
                          />

                          <div className="form-text">
                            滑块条依次为：色调、饱和度、值、透明度、冷暖
                          </div>
                        </div>
                      </div>
                      <div className="col-7">
                        <IroItem
                          inputColor={form.color}
                          selectColorModeRef={selectColorModeRef}
                          changeColorCallback={changeColorCallback}
                        />
                      </div>
                    </div>
                  </div>
                )}

                {form.name &&
                  (form.colorMode === 'CUSTOM' ||
                    form.backgroundColorMode === 'CUSTOM') && (
                    <div className="card position-relative">
                      <div className="card-body text-center">
                        <div
                          className="position-absolute text-muted"
                          style={{
                            left: '-1rem',
                            top: '-0.7rem',
                            transform: 'skew(15deg)',
                          }}
                        >
                          预览
                        </div>
                        <span
                          className={classNames(
                            'badge me-2',
                            form.roundedPill ? 'rounded-pill' : false,
                          )}
                          style={{
                            color:
                              form.colorMode === 'DEFAULT'
                                ? '#ffffff'
                                : form.color,
                            backgroundColor:
                              form.backgroundColorMode === 'DEFAULT'
                                ? '#0dcaf0'
                                : form.backgroundColor,
                          }}
                        >
                          {form.name}
                        </span>
                        <span>{details.basic.name}</span>
                      </div>
                    </div>
                  )}

                <div>
                  <label className="form-label">背景颜色模式</label>
                  <div className="form-control user-select-none">
                    {Object.keys(BADGE_BACKGROUND_COLOR_MODE).map((item) => {
                      return (
                        <div
                          key={item}
                          className="form-check form-check-inline"
                        >
                          <input
                            id={`yw-badge-backgroundColorMode-${item}`}
                            name="backgroundColorMode"
                            className="form-check-input"
                            type="radio"
                            onChange={onChangeForm}
                            value={item}
                            checked={form.backgroundColorMode === item}
                          />
                          <label
                            className="form-check-label"
                            htmlFor={`yw-badge-backgroundColorMode-${item}`}
                          >
                            {BADGE_BACKGROUND_COLOR_MODE[item]}
                          </label>
                        </div>
                      );
                    })}
                  </div>
                </div>

                {form.backgroundColorMode === 'CUSTOM' && (
                  <div>
                    <label className="form-label">背景颜色</label>
                    <div className="row align-items-center gap-4">
                      <div className="col-4">
                        <div className="vstack gap-4">
                          <div className="row gap-4 align-items-center">
                            <div className="col-2"></div>
                            <div className="col">
                              <select
                                ref={selectBackgroundColorModeRef}
                                name="selectBackgroundColorMode"
                                value={selectBackgroundColorMode}
                                onChange={onChangeForm}
                                className="form-select"
                                aria-label="selectBackgroundColorMode"
                                placeholder="请选择背景颜色输出类型"
                              >
                                <option value="HEX">HEX</option>
                                <option value="RGB">RGB</option>
                                <option value="RGBA">RGBA</option>
                                <option value="HSL">HSL</option>
                                <option value="HSLA">HSLA</option>
                              </select>
                            </div>
                          </div>

                          <input
                            type="text"
                            className="form-control"
                            name="backgroundColor"
                            value={form.backgroundColor}
                            onChange={onChangeForm}
                            aria-describedby="backgroundColor"
                            placeholder="请输入背景颜色"
                          />

                          <div className="form-text">
                            滑块条依次为：色调、饱和度、值、透明度、冷暖
                          </div>
                        </div>
                      </div>
                      <div className="col-7">
                        <IroItem
                          inputColor={form.backgroundColor}
                          selectColorModeRef={selectBackgroundColorModeRef}
                          changeColorCallback={changeBackgroundColorCallback}
                        />
                      </div>
                    </div>
                  </div>
                )}

                <div>
                  <label className="form-label">椭圆形样式</label>
                  <select
                    name="roundedPill"
                    value={form.roundedPill + ''}
                    onChange={onChangeForm}
                    className="form-select"
                    aria-label="roundedPill"
                    placeholder="请选择是否椭圆形样式"
                  >
                    <option value="false">否</option>
                    <option value="true">是</option>
                  </select>
                </div>
              </>
            )}

            <button
              type="submit"
              disabled={
                createPostBadgeMutation.isLoading ||
                updatePostBadgeMutation.isLoading
              }
              className={classNames(
                'btn w-25 my-4',
                currentItemId ? 'btn-success' : 'btn-primary',
              )}
            >
              {(createPostBadgeMutation.isLoading ||
                updatePostBadgeMutation.isLoading) && (
                <span
                  className="spinner-border spinner-border-sm me-2"
                  role="status"
                  aria-hidden="true"
                ></span>
              )}
              {currentItemId ? '更新' : '添加'}
            </button>
          </form>
        </div>
      </div>
    </div>
  );
}
